

package graph

import "fmt";
import "container/vector";




type Edge struct {
    v Vertex;
    weight int64;
}


func (e *Edge) String() string {
    return fmt.Sprintf("-> %s : %d", e.v, e.weight);
}


func (e *Edge) GetVertex() (Vertex) {
    return e.v;
}

func (e *Edge) GetWeight() (int64) {
    return e.weight;
}


type Graph struct {
    adjList map[Vertex] *vector.Vector;
    directed bool;
}



// Iterate over all elements; driver for range
func (g *Graph) iterate(c chan<- interface{}) {
	for v, _ := range g.adjList {
		c <- v
	}
	close(c);
}

func (g *Graph) GetVertices() <-chan interface{} {
    c := make(chan interface{});
	go g.iterate(c);
	return c;
} 


func (g *Graph) GetEdges(n Vertex)  <-chan interface{} {
    return g.adjList[n].Iter();
}




func (g *Graph) AddEdgeWithWeight(from Vertex, to Vertex, weight int64) {
    g.AddNode(from);
    g.AddNode(to);
    edge := Edge {to, weight};
    g.adjList[from].Push(&edge);
    if !g.directed {
        edge2 := Edge {from, weight};
        g.adjList[to].Push(&edge2);
    }
}


func (g *Graph) AddEdge(from Vertex, to Vertex) {
    g.AddEdgeWithWeight(from, to, 0);
}


func (g *Graph) AddNode(n Vertex) bool {
    _, present := g.adjList[n];
    if present {
        return false;
    }
    g.adjList[n] = vector.New(0);
    return true;
}



func NewGraph(directed bool) *Graph {
    adjList := make(map[Vertex] *vector.Vector);
    return &Graph{adjList, directed};
}


func (g *Graph) String() string {
    var s string = "";
    for node, neighbors := range g.adjList {
        s += fmt.Sprintf("%d", node)       ;
        s += ": ";
        for i := 0; i < neighbors.Len(); i++ {
            var neigh *Edge = neighbors.At(i).(*Edge);
            s += fmt.Sprintf("%d,", neigh.v);
        }
        s += "\n";
    }
    return s;
}




